package com.netty.client.udp;

import com.netty.coder.ObjectDecoder;
import com.netty.coder.ObjectEncoder;
import com.netty.handler.LoggingHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramChannel;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.stream.ChunkedWriteHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ImUdpClient {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private Integer port = 23456;

    private Channel channel;

    private ImUdpClientHandler imUdpClientHandler;

    public Channel startClient() {
        EventLoopGroup group = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group);
        bootstrap.channel(NioDatagramChannel.class)
                .option(ChannelOption.SO_BROADCAST,true)
                .option(ChannelOption.SO_RCVBUF, 2048 * 1024)// 设置UDP读缓冲区为2M
                .option(ChannelOption.SO_SNDBUF, 1024 * 1024)// 设置UDP写缓冲区为1M
                .handler(new ChannelInitializer<DatagramChannel>() {
                    @Override
                    public void initChannel(DatagramChannel ch) throws Exception {
                        ChannelPipeline pipeline = ch.pipeline();
                        //日志输出
                        pipeline.addLast(new LoggingHandler());
                        // 主要用于处理大数据流，比如一个1G大小的文件如果你直接传输肯定会撑暴jvm内存的; 增加之后就不用考虑这个问题了
                        pipeline.addLast(new ChunkedWriteHandler());
                        pipeline.addLast(new StringDecoder());
                        pipeline.addLast(new StringEncoder());
//                        pipeline.addLast(new ObjectDecoder(Object::getClass));
//                        pipeline.addLast(new ObjectEncoder());
                        pipeline.addLast("handler", new UdpClientHandler(imUdpClientHandler));
                    }
                });

        ChannelFuture channelFuture = bootstrap.bind(port).syncUninterruptibly();
        channelFuture.channel().newSucceededFuture().addListener(future -> {
            String logBanner = "\n\n" +
                    "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" +
                    "*                                                                                   *\n" +
                    "*                                                                                   *\n" +
                    "*                   udp Server started on port {}.                           *\n" +
                    "*                                                                                   *\n" +
                    "*                                                                                   *\n" +
                    "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n";
            logger.info(logBanner, port);
        });
        channelFuture.channel().closeFuture().addListener(future -> this.destroy(group));
        channel = channelFuture.channel();
        return channel;
    }

    /**
     * 销毁队列
     */
    public void destroy(EventLoopGroup workerGroup) {
        logger.info(">>>>>>>>>>>>>>>>>>>>>>destroy server<<<<<<<<<<<<<<<<<<<<<<");
        workerGroup.shutdownGracefully();
        logger.info(">>>>>>>>>>>>>>>>>>>>>>destroy server complate.<<<<<<<<<<<<<<<<<<<<<<");
    }

    //5秒钟后自动重连
    public void restartClient(){
        try {
            Thread.sleep(5000);
            startClient();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public ImUdpClient(ImUdpClientHandler imUdpClientHandler) {
        this.imUdpClientHandler = imUdpClientHandler;
    }
    public ImUdpClient(Integer port, ImUdpClientHandler imUdpClientHandler) {
        this.port = port;
        this.imUdpClientHandler = imUdpClientHandler;
    }

}
